﻿using Consul;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace ConsulDiscovery.Models
{
    public interface IServiceDiscoveryProvider
    {
        Task<List<string>> GetServicesAsync();
    }

    public class PollServiceDisconveryProvider : IServiceDiscoveryProvider
    {

        private static readonly PollServiceDisconveryProvider INSTANCE = new PollServiceDisconveryProvider();
        public static PollServiceDisconveryProvider GetInstance
        {
            get
            {
                return INSTANCE;
            }
        }

        private static Logger LOG = LogManager.GetCurrentClassLogger();
        private List<string> _serviceCache = new List<string>();
        private Timer _timer;
        private bool _polling;


        private PollServiceDisconveryProvider()
        {
            _timer = new Timer(async _ =>
            {
                if (_polling)
                    return;

                _polling = true;
                LOG.Debug("从consul刷新服务列表开始.");
                await Poll();
                LOG.Debug("从consul刷新服务列表完成: service: {0}.", _serviceCache.Count());
                _polling = false;

            }, null, 0, 10000);
            
        }

        public async Task<List<string>> GetServicesAsync()
        {
            if (_serviceCache.Count == 0)
            {
                await Poll();
                
            }
            return _serviceCache;
        }

        private async Task Poll()
        {
            _serviceCache = await new ServiceDiscoveryProvider().GetServicesAsync();
        }

    }

    public class ServiceDiscoveryProvider : IServiceDiscoveryProvider
    {
        public async Task<List<string>> GetServicesAsync()
        {
            var consulClient = new ConsulClient(new ConsulClientConfiguration
            {
                Address = new Uri("http://localhost:8500")
            });

            var serviceId = "Service";

            var results = await consulClient.Health.Service(serviceId);

            var ret = new List<string>();

            foreach (var item in results.Response)
            {
                ret.Add(item.Service.Address + ":" + item.Service.Port);
            }

            return ret;

        }
    }
}